<template>
	<cl-dialog
		width="1100px"
		:visible.sync="visible"
		@close="close"
		:props="{
			top: '5vh',
			beforeClose: beforeClose,
			customClass: 'appoint-board__dialog',
			'append-to-body': true,
			'close-on-click-modal': false,
			'close-on-press-escape': false
		}"
		title=""
		:controls="['slot-expand', 'cl-flex1', 'fullscreen', 'close']"
	>
		<template #slot-expand>
			<div class="flex flex-align-end board-title">
				<h3 class="pr-2">预约看板</h3>
				<cl-filter label="门店老师数：">{{ condition.teacher }}人</cl-filter>；
				<cl-filter label="床位数：">{{ condition.bed || currShop.bed || 0 }}张</cl-filter>；
				<cl-filter label="预约数：">{{
					condition.cart_num || currShop.cart_num || 0
				}}</cl-filter>
				<cl-filter label="；专场：" v-if="shopActivity"
					>{{ shopActivity.begin_time }} ~ {{ shopActivity.end_time }}</cl-filter
				>
				<el-button type="primary" class="set-teacher-btn" @click="setTeacher"
					>配置营业老师</el-button
				>
			</div>
		</template>
		<div class="container" v-loading="loading">
			<filter-wrap
				ref="filter"
				v-model="search"
				:loading="loading"
				@search="getData()"
				@reset="getData()"
			/>
			<color-blocks />
			<div class="board-container" ref="timeBeds">
				<timeline :list="times" :recent-time="recentTime" />
				<time-beds
					:condition="condition"
					:beds="currShop.bed"
					:shop="currShop"
					:recent-time="recentTime"
					:panels="panels"
					:is-today="isToday"
					:is-before-day="isBeforeDay"
					:is-after-day="isAfterDay"
					@to-shop="toShop"
					@cell-click="handleCellClick"
					@cell-dragenter="handleCellDragenter"
				>
					<el-popover
						v-for="item in list"
						:key="'item' + item.cart_id"
						placement="right-start"
						trigger="click"
						:disabled="item.darg"
					>
						<appoint-info :info="item" @edit-appoint="openAppointForm(item, true)" />
						<div
							slot="reference"
							class="list-item"
							:class="{ 'is-have': item.status == 1 }"
							:style="item.style"
							:draggable="item.status == 1 && isToday"
							@dragstart="handleDragstart(item, $event)"
							@dragend="handleDragend(item, $event)"
						>
							<div class="avatar" v-if="item.row > 3">
								<cl-avatar :src="cusCover(item)" />
								<div
									class="cus_type"
									:style="{ backgroundImage: `url(${item.type_bg})` }"
								>
									{{ item.cus_type | constFilter("CUS_TYPE") }}
								</div>
							</div>
							<div class="name ellipsis" v-if="item.row > 1">
								{{ item.cus_name || "客户名称" }}
							</div>
							<div class="time" v-if="item.row > 2">
								{{ item.begin_time }} ~ {{ item.end_time }}
							</div>
							<ul class="projects">
								<li v-for="(v, i) in item.projects" :key="i">{{ v }}</li>
							</ul>
						</div>
					</el-popover>
				</time-beds>
			</div>
		</div>
		<cl-appoint-form ref="appointForm" @confirm="getData()" />
		<appoint-form
			ref="addAppoint"
			@edit-appoint="openAppointForm"
			@to-maintain="toMaintain"
			@confirm="getData()"
		/>
		<maintain-form ref="maintain" @confirm="getData()" />
		<set-business-teacher ref="setTeacher" @confirm="getData()" />
	</cl-dialog>
</template>
<script>
//维护
import MaintainForm from "@/cool/modules/customer/components/maintain-form.vue";
import ColorBlocks from "./color-blocks";
import Timeline from "./timeline";
import TimeBeds from "./time-beds";
import AppointInfo from "./appoint-info";
import AppointForm from "./appoint-form";
import FilterWrap from "./filter-wrap";
import SetBusinessTeacher from "./set-business-teacher";
import dayjs from "dayjs";
import { last, isEmpty } from "cl-admin/utils";
export default {
	components: {
		MaintainForm,
		ColorBlocks,
		Timeline,
		TimeBeds,
		AppointInfo,
		AppointForm,
		FilterWrap,
		SetBusinessTeacher
	},
	data() {
		return {
			visible: false,
			saving: false,
			loading: false,
			search: {
				biz_id: "",
				dept_id: "", //所属
				appoint_date: dayjs().format("YYYY-MM-DD")
			},
			times: [],
			panels: [],
			condition: { teacher: 0, bed: 0 },
			list: [],
			dragenterCell: null,
			recentTime: {
				fulltime: "",
				time: "",
				top: 0
			}
		};
	},
	computed: {
		shopActivity() {
			const { activity_list } = this.currShop;
			return activity_list?.[0];
		},
		isToday() {
			const { appoint_date } = this.search;
			if (!appoint_date) return false;
			return dayjs(appoint_date).isSame(dayjs(), "d");
		},
		isBeforeDay() {
			const { appoint_date } = this.search;
			if (!appoint_date) return false;
			return dayjs(appoint_date).isBefore(dayjs(), "d");
		},
		isAfterDay() {
			const { appoint_date } = this.search;
			if (!appoint_date) return false;
			return dayjs(appoint_date).isAfter(dayjs(), "d");
		},
		// 营业开始时间
		btime() {
			const { btime } = this.currShop;
			const { appoint_date } = this.search;
			let time = dayjs(appoint_date + " " + (btime || "00:00"));
			if (time.minute() != 0) {
				time = time.minute() > 30 ? time.add(1, "h").set("m", 0) : time.set("m", 30);
			}
			return time.format("YYYY-MM-DD HH:mm");
		},
		// 营业结束时间
		etime() {
			const { etime } = this.currShop;
			const { appoint_date } = this.search;
			let time = dayjs(appoint_date + " " + (etime || "23:30"));
			if (time.minute() != 0) {
				time = time.minute() > 30 ? time.add(1, "h").set("m", 0) : time.set("m", 30);
			}
			return time.format("YYYY-MM-DD HH:mm");
		},
		shopList() {
			const { biz_id } = this.search;
			return this.getBizRefData(biz_id, "shop_childs");
		},
		currShop() {
			const { dept_id } = this.search;
			if (!dept_id) return {};
			let res = this.shopList.find(v => v.dept_id == dept_id);
			return res || {};
		}
	},
	created() {
		this.search.biz_id = this.getCurrBiz();
	},
	methods: {
		open(data = {}) {
			this.visible = true;
			this.search.biz_id = data.biz_id || this.getCurrBiz();

			this.$nextTick(async () => {
				this.loading = true;
				await this.$refs.filter.init();
				if (data.dept_id) {
					this.search.dept_id = data.dept_id;
				}
				console.log("search", data.biz_id, this.search);

				setTimeout(() => {
					this.$refs.filter.search();
				}, 0);
			});
		},
		close() {
			this.$refs.filter.reset(false);
			this.visible = false;
		},
		beforeClose(done) {
			!this.saving && done();
		},
		setTeacher() {
			const { dept_id, appoint_date } = this.search;
			const { teacher } = this.condition;
			this.$refs.setTeacher.open({
				shop_id: dept_id,
				date: appoint_date,
				business_num: teacher
			});
		},
		// 获取预约数据
		async getData(scrollTo = true) {
			// console.log("search", this.search);
			this.loading = true;
			this.calcTimeBed();
			this.changeShop();
			const res = await this.$service.cart.cartBoard(this.search).finally(() => {
				this.loading = false;
			});

			this.condition = res.condition;
			// console.log("res", res);
			this.$nextTick(() => {
				this.calcDataOffset(res.list || []);
				if (scrollTo) {
					const { top } = this.recentTime;
					this.$refs.timeBeds?.scrollTo?.({ top: top - 3 });
				}
			});
		},
		// 处理最近时间
		initRecentTime() {
			this.recentTime = {
				fulltime: "",
				time: "",
				top: 0
			};
			let btime = dayjs(this.btime);
			let etime = dayjs(this.etime);

			if (this.isToday && btime.isSame(dayjs(), "d")) {
				let now = dayjs();
				now = now.minute() > 30 ? now.add(1, "h").set("m", 0) : now.set("m", 30);
				let minute = now.diff(btime, "m");
				let row = minute / 30;
				// 现在时刻在营业开始时间之前
				if (now.isBefore(btime)) {
					row = 0;
				}
				// 现在时刻在营业结束时间之后
				if (now.isAfter(etime)) {
					row = this.times.length;
				}
				this.recentTime = {
					fulltime: now.format("YYYY-MM-DD HH:mm"),
					time: now.format("HH:mm"),
					top: row * 50
				};
			}
			this.panels.forEach(v1 => {
				v1.forEach(v2 => this.cellDisable(v2));
			});
		},
		// 计算预约初始定位
		calcDataOffset(data = []) {
			let btime = dayjs(this.btime);
			let list = data.map(v => {
				let start = dayjs(btime.format("YYYY-MM-DD") + v.begin_time);
				let end = dayjs(btime.format("YYYY-MM-DD") + v.end_time);
				// 开始cell/结束cell
				let coord = {
					x1: v.bed - 1,
					y1: start.diff(btime, "m") / 30,
					x2: v.bed - 1,
					y2: end.diff(btime, "m") / 30
				};
				let row = coord.y2 - coord.y1;

				// 每格坐标
				let location = [];
				for (let i = 0; i < row; i++) {
					location.push({
						x: coord.x1,
						y: coord.y1 + i
					});
				}
				// 重置cell占用状态
				// console.log("开始cell/结束cell", coord);
				this.resetPanelUse(coord.x1, coord.y1, coord.y2, true);
				// console.log("item", v);
				let res = {
					row,
					coord,
					location,
					type_bg: require(`@/assets/img/${this.$constFilter(
						v.cus_type,
						"CUS_TYPE",
						"type"
					)}.png`),
					style: {
						top: coord.y1 * 50 + "px",
						left: coord.x2 * 110 + "px",
						height: row * 50 + "px"
					},
					drag: false,
					saving: false,
					...v,
					appoint_date: v.appoint_time,
					appoint_btime: v.btime,
					appoint_etime: v.etime,
					projects: !v.projects ? [] : v.projects.split(",")
				};
				return {
					...res,
					backup: { ...res }
				};
			});
			// console.log(list);
			this.list = list;
		},
		// 计算床位与时间关系坐标
		calcTimeBed() {
			this.panels = [];
			let times = [];
			const { appoint_date } = this.search;
			let start = dayjs(this.btime);
			let end = dayjs(this.etime);

			let minute = end.diff(start, "m");
			let rows = minute / 30;
			for (let i = 0; i < rows; i++) {
				times.push({
					date: appoint_date,
					start: start.add(30 * i, "m").format("HH:mm"),
					end: start.add(30 * (i + 1), "m").format("HH:mm")
				});
			}
			let panels = Array(this.currShop.bed || 0)
				.fill([])
				.map((v1, x) => {
					return times.map((v2, y) => ({
						...v2,
						bed: x + 1,
						x,
						y,
						hover: false,
						use: false,
						recent_before: false
					}));
				});

			this.times = times;
			this.panels = panels;
			this.initRecentTime();
			// this.$refs.timeBeds?.scrollTo?.({ top: 0 });
		},
		// 门店切换
		changeShop() {
			if (isEmpty(this.currShop)) return false;
			if (this.currShop.bed > 0) return false;
			this.confirm(`门店“${this.currShop.dept_name}”还未配置床位，是否前往配置？`)
				.then(() => {
					this.toShop();
				})
				.catch(() => {});
			return true;
		},
		toShop() {
			this.close();
			this.$router.push({ name: "CrmPersonnelStore" });
		},
		// 拖拽元素到cell
		handleCellDragenter(cell) {
			console.log("cell", `x=${cell.x},y=${cell.y}`);
			// 如果单元格已使用或禁用状态
			if (cell.use || cell.recent_before) return;
			this.dragenterCell = cell;
		},
		cellDisable(cell) {
			cell.recent_before = false;
			const { fulltime } = this.recentTime;
			if (!fulltime) return;
			let recentTime = dayjs(fulltime);
			let cellTime = dayjs(cell.date + cell.start);
			cell.recent_before = cellTime.isBefore(recentTime);
		},
		// 拖拽开始
		handleDragstart(item) {
			item.drag = true;
		},
		// 拖拽结束
		handleDragend(item) {
			let cell = this.dragenterCell;
			const { coord } = item;
			item.drag = false;
			this.dragenterCell = null;
			const { teacher } = this.condition;
			if (cell) {
				if (cell.bed > teacher) return;
				// 如果cell单元格已被使用
				if (cell.use) {
					console.log("如果cell单元格已被使用", cell.use);
					this.$message.warning("不可修改预约到该时间点");
					return;
				}
				// 所需占用格子
				let placeCell = [];
				for (let i = 0; i < item.row; i++) {
					let panel = this.panels[cell.x][cell.y + i];
					if (!panel) break;
					placeCell.push(panel);
				}
				// 所需格子数不足
				if (placeCell.length != item.row) {
					console.log("所需格子数不足", placeCell.length != item.rows);
					this.$message.warning("不可修改预约到该时间点");
					return;
				}
				let lastCell = last(placeCell);
				// 检测除自己意外的单元格是否被占用
				let isUse = placeCell
					.filter(v1 => !item.location.some(v2 => v2.x == v1.x && v2.y == v1.y))
					.some(v => v.use);
				// isUse 如果床位相同且placeCell某一格已被使用 且拖拽元素坐标与其不相同
				if (isUse) {
					this.$message.warning("不可修改预约到该时间点", isUse);
					return;
				}

				this.confirm(`是否保存当前床位和时间？`)
					.then(() => {
						//重置单元格使用状态
						this.resetPanelUse(coord.x1, coord.y1, coord.y2);
						// 床位
						item.bed = cell.bed;
						// 定位
						item.style.top = cell.y * 50 + "px";
						item.style.left = cell.x * 110 + "px";
						item.appoint_time = cell.date + " " + cell.start;
						item.appoint_date = cell.date + " " + cell.start;
						// 预约时间
						item.begin_time = cell.start;
						item.end_time = lastCell.end;
						item.appoint_btime = cell.start;
						item.appoint_etime = lastCell.end;
						// 坐标
						item.coord = {
							x1: cell.x,
							y1: cell.y,
							x2: lastCell.x,
							y2: lastCell.y
						};
						item.location = placeCell.map(v => ({
							x: v.x,
							y: v.y
						}));
						delete item.backup;
						item.backup = { ...item };
						// 标记修改后的坐标已使用
						this.resetPanelUse(item.coord.x1, item.coord.y1, item.coord.y2, true);
						this.updateAppoint(item);
						this.initRecentTime();
					})
					.catch(() => {});
			}
		},
		// 更新预约
		async updateAppoint(item) {
			let items = (item?.service_info || []).map(v => ({
				type: v.type || 1,
				id: v.id,
				prod_id: v.id,
				name: v.name,
				lasttime: v.lasttime,
				picture_url: v.picture_url,
				product_category: v.product_category,
				unit_price: v.price,
				price: v.price,
				maintain_type: v.maintain_type || 0,
				is_presents: v.is_presents,
				is_experience: v.is_experience
			}));
			let form = {
				bed: item.bed,
				cart_id: item.cart_id,
				biz_id: item.biz_id, //事业部id
				dept_id: item.dept_id, //门店id
				bra_id: item.bra_id,
				add_dept_id: item.add_dept_id, //预约部门
				add_user_id: item.add_user_id, //预约人
				// dept_ids: [],
				cus_id: item.cus_id, //客户名
				cus_mobile: item.cus_mobile, //客户手机
				appoint_time: item.appoint_time,
				appoint_date: dayjs(item.appoint_date).format("YYYY-MM-DD"), //预约日期
				appoint_btime: item.begin_time, //预约开始时间
				appoint_etime: item.end_time, //预约结束时间
				items: JSON.stringify(items), //已选服务列表
				remarks: item.remarks || "" //备注信息
			};
			item.saving = true;
			await this.$service.cart
				.update(form)
				// .catch(e => {
				// 	this.confirm("是否前往改约?").then(() => {
				// 		this.openAppointForm(item);
				// 	});
				// 	throw e;
				// })
				.done(() => {
					this.saving = false;
					this.initRecentTime();
				});
			this.getData(false);
			this.$emit("refresh");
			this.$message.success("操作成功");
			// console.log(form);
		},
		// 重置use状态
		resetPanelUse(x1 = 0, y1 = 0, y2 = 0, use = false) {
			if (!this.panels.length) return;
			let row = y2 - y1;
			if (row <= 0) return;
			for (let i = 0; i < row; i++) {
				let cells = this.panels[x1] || [];
				let cell = cells[y1 + i];
				if (!cell) break;
				cell.use = use;
			}
		},
		// 客户头像
		cusCover(item) {
			if (item.cus_img) return item.cus_img;
			return require(`@/assets/img/${item.cus_sex == 2 ? "women" : "men"}.png`);
		},
		// 单元格点击
		handleCellClick(cell) {
			if (this.isBeforeDay || cell.recent_before) return;
			let nextCell = this.panels[cell.x][cell.y + 1];
			// for (let i = 0; i < 4; i++) {
			// 	let item = this.panels[cell.x][cell.y + i];
			// 	if (!item || item.use) {
			// 		this.$message.warning("当前时间不可添加预约");
			// 		return;
			// 	}
			// }
			if (cell.use) {
				this.$message.warning("当前时间不可添加预约");
				return;
			}

			const { biz_id, dept_id } = this.search;
			// let cart_duration = !nextCell || nextCell.use ? 30 : 120;
			// let appoint_time = dayjs(`${cell.date} ${cell.start}`);
			this.$refs.addAppoint.open({
				biz_id,
				dept_id,
				bed: cell.bed,
				appoint_btime: cell.start,
				appoint_date: cell.date, //预约日期
				appoint_time: `${cell.date} ${cell.start}`
				// appoint_etime: appoint_time.add(cart_duration, "m").format("HH:mm"),
				// cart_duration
			});
		},
		// 预约表单
		openAppointForm(data = {}) {
			this.$refs.appointForm.open(data, true);
		},
		// 维护
		toMaintain(cus, form) {
			const { biz_id, dept_id } = form;
			console.log(form);
			let data = {
				cus_id: cus.cus_id,
				biz_id,
				dept_id,
				appoint_time: form.appoint_time,
				appoint_date: form.appoint_date, //预约日期
				appoint_btime: form.appoint_btime //预约开始时间
			};
			this.$refs.maintain.open(data);
		}
	}
};
</script>
<style lang="scss" scoped>
//用什么插件必须引入相应的样式表，否则不能正常显示
::v-deep .appoint-board__dialog {
	.el-dialog__header {
		padding: 10px 15px !important;
		// .board-title {
		// 	.cl-filter {
		// 		margin: 0;
		// 		&__label {
		// 			font-size: 14px;
		// 			color: #7a7a7a;
		// 			margin-right: 0;
		// 		}
		// 	}
		// }
	}
	.el-dialog__body {
		height: 78vh;
		overflow: hidden;
		padding: 20px;
		box-sizing: border-box;
		.cl-dialog__container {
			height: 100%;
			overflow: hidden;
		}
	}
	&.is-fullscreen {
		.el-dialog__body {
			height: 85vh;
		}
	}
	.container {
		height: 100%;
		display: flex;
		flex-direction: column;
		position: relative;
	}
	.board {
		&-title {
			font-size: 14px;
			position: relative;
			z-index: 1000;
			.cl-filter {
				margin: 0;
				&__label {
					font-size: 14px;
					color: #7a7a7a;
					margin-right: 0;
				}
			}
			.set-teacher-btn {
				width: auto;
				background-color: #156DFF;
				border-color: #156DFF;
				margin-left: 10px;
			}
		}
		&-container {
			flex: 1;
			overflow: auto;
			position: relative;
			padding-bottom: 70px;
			.list-item {
				position: absolute;
				z-index: 5;
				width: 110px;
				height: 110px;
				background: $color-success;
				box-shadow: 1px 0 0 0 #fff, 0 1px 0 0 #fff, 1px 1px 0 0 #fff, inset 1px 0 0 0 #fff,
					inset 0 1px 0 0 #fff;
				font-size: 12px;
				display: flex;
				flex-direction: column;
				align-items: center;
				color: #fff;
				padding: 10px;
				box-sizing: border-box;
				cursor: pointer;
				overflow: hidden;

				&.is-have {
					cursor: move;
					background: $color-primary;
				}
				.name,
				.time {
					margin-bottom: 4px;
				}

				.avatar {
					position: relative;
					margin-bottom: 12px;
					.el-image__inner {
						pointer-events: none;
					}
					.cus_type {
						position: absolute;
						bottom: -8px;
						left: 50%;
						transform: translateX(-50%);
						font-size: 12px;
						box-sizing: border-box;
						width: 40px;
						height: 20px;
						line-height: 18px;
						background-size: 100%;
						background-repeat: no-repeat;
					}
				}
				.name {
					width: 100%;
				}
				.projects {
					flex: 1;
					overflow: hidden;
				}
			}
		}
	}
}
</style>
